package com.hjh.core.activity

import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.os.Environment
import com.elvishew.xlog.LogConfiguration
import com.elvishew.xlog.LogLevel
import com.elvishew.xlog.XLog
import com.elvishew.xlog.flattener.PatternFlattener
import com.elvishew.xlog.printer.AndroidPrinter
import com.elvishew.xlog.printer.file.FilePrinter
import com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy2
import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy
import com.hjh.core.framework.BaseXLogFileNameGenerator
import com.hjh.tool.util.sys.SysUtil
import com.hjq.toast.Toaster
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File

@Suppress("unused")
open class BaseApplication : Application() {

    override fun onCreate() {
        appContext = applicationContext

        super.onCreate()

        Toaster.init(this)
    }

    fun initXLog(
        tag: String = "XLog",
        logPrefix: String = "",
        debug: Boolean = false,
    ) {
        CoroutineScope(Dispatchers.Default).launch {
            val xLogConfigBuilder = LogConfiguration.Builder()
                .tag(tag)
                .logLevel(LogLevel.ALL)
                .enableStackTrace(2)

            if (debug) {
                xLogConfigBuilder
                    .enableBorder()
            }

            val xLogConfig = xLogConfigBuilder.build()
            val androidPrinter = AndroidPrinter(true)
            // 打印(保存)日志到文件的打印机
            LOG_DIR?.path?.let {
                val filePrinter =
                    FilePrinter
                        .Builder(it) // 指定日志文件的目录路径
                        .fileNameGenerator(BaseXLogFileNameGenerator(logPrefix)) // 自定义文件名称 默认值: ChangelessFileNameGenerator(“日志”)
                        .backupStrategy(
                            FileSizeBackupStrategy2(
                                3 * 1024 * 1024,
                                10
                            )
                        ) // 单个日志文件的大小默认:FileSizeBackupStrategy2(3 * 1024 * 1024, 10)
                        .cleanStrategy(FileLastModifiedCleanStrategy(14L * 24L * 60L * 60L * 1000L)) // 日志文件存活时间，单位毫秒
                        .flattener(PatternFlattener("{d} {l}/{t}: {m}")) // 自定义flattener，控制打印格式
                        .build()
                XLog.init(
                    xLogConfig,
                    androidPrinter,
                    filePrinter
                )
            } ?: run {
                XLog.init(
                    xLogConfig,
                    androidPrinter
                )
            }
        }
    }

    fun initStorageDirs(dir: String) {
        val baseDir = if (SysUtil.isSystemApp(this)) {
            // 系统应用直接使用外部存储根目录
            getSystemAppStorageDir(dir)
        } else {
            // 非系统应用：先尝试外部存储，失败后使用应用专属目录
            getNormalAppStorageDir(dir)
        }
        initBaseDir(baseDir)
    }

    private fun getSystemAppStorageDir(dir: String): File {
        // 系统应用直接使用 Environment.getExternalStorageDirectory()
        val sdCardDir = Environment.getExternalStorageDirectory()
        return File(sdCardDir, dir).apply {
            if (!exists()) {
                mkdirs()
            }
        }
    }

    private fun getNormalAppStorageDir(dir: String): File {
        // 先尝试外部存储目录
        val sdCardDir = Environment.getExternalStorageDirectory()
        val externalStorageDir = File(sdCardDir, dir)

        return if (canUseExternalStorage(externalStorageDir)) {
            externalStorageDir
        } else {
            // 外部存储不可用，回退到应用专属目录
            val appSpecificDir = File(appContext.getExternalFilesDir(null), dir)
            appSpecificDir.apply {
                if (!exists()) {
                    mkdirs()
                }
            }
        }
    }

    private fun canUseExternalStorage(dir: File): Boolean {
        return try {
            // 检查是否有权限
            if (Environment.MEDIA_MOUNTED != Environment.getExternalStorageState()) {
                return false
            }

            // 检查目录是否可读写
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    return false
                }
            }

            // 实际测试写入权限
            val testFile = File(dir, ".test")
            testFile.createNewFile()
            testFile.delete()
            true
        } catch (e: Exception) {
            false
        }
    }

    companion object {
        @SuppressLint("StaticFieldLeak")
        lateinit var appContext: Context
            private set

        @Volatile
        private var baseDir: File? = null

        /**
         * 初始化基础目录
         * @param customDir 若为 null 则使用默认目录：/sdcard/appName
         */
        private fun initBaseDir(customDir: File? = null) {
            baseDir = customDir ?: File(appContext.getExternalFilesDir(null), "appName")
        }

        /**
         * 获取基础目录
         */
        val BASE_FILE_DIR: File?
            get() = baseDir

        /**
         * 获取某个模块的目录，例如模块名为 "log"，返回 /sdcard/appName/log
         * 自动创建目录（如不存在）
         */
        fun getModuleDir(moduleName: String): File? {
            val dir = baseDir?.let { File(it, moduleName) }
            dir?.mkdirs()
            return dir
        }

        /**
         * 获取日志模块目录：相当于 getModuleDir("log")
         */
        val LOG_DIR: File?
            get() = getModuleDir("log")

        /**
         * 获取数据缓存目录：相当于 getModuleDir("cache")
         */
        val CACHE_DIR: File?
            get() = getModuleDir("cache")
    }
}